package org.client.otdr;

import org.openems.entity.Entity;
import org.openems.entity.ListEntity;
import org.openems.entity.MarkerEntity;
import org.openems.entity.NumericEntity;

import framework.DomainService;
import framework.EntityStoreListener;
import framework.mashup.GoogleMap;
import framework.mashup.GoogleMapListener;
import framework.mashup.LatLng;
import org.openems.entity.Key;

public class OtdrMap {
	public GoogleMap getGoogleMap() {
		return googleMap;
	}
	private GoogleMap googleMap;

	public OtdrMap(final DomainService service, boolean controlVisible) {
		googleMap = new GoogleMap(controlVisible);
		this.googleMap.setPrefSize(400, 300);
		initialize(service);	
	}

	private void initialize(final DomainService service) {
		final OTDRID id = OTDRID.get();
		final LatLng[] nodes = {				
			new LatLng(35.447631,139.342175),
			new LatLng(35.445651,139.347008),
			new LatLng(35.44458,139.351197),
			new LatLng(35.443732,139.357967),
			new LatLng(35.460705,139.359469),
			new LatLng(35.462627,139.359984),
			new LatLng(35.465179,139.363375),
			new LatLng(35.465284,139.366078),
			new LatLng(35.463816,139.393115),
			new LatLng(35.463956,139.401226),
			new LatLng(35.465703,139.405432),
			new LatLng(35.477586,139.416847),
			new LatLng(35.478984,139.42071),
			new LatLng(35.478495,139.44294),
		};	
		
		class EntityStoreListenerImpl implements EntityStoreListener {
			private int number;
			private boolean focus;
			public EntityStoreListenerImpl(int number, boolean focus) {
				this.number = number;
				this.focus = focus;
			}
			@Override
			public void valueChanged(Entity entity) {
				moveMarker(googleMap, nodes, ((NumericEntity)entity).getValue()*1000, this.number, focus);
			}
		};
		
		service.addEntityStoreListener(new EntityStoreListener() {
			@Override
			public void valueChanged(Entity entity) {
				service.addEntityStoreListener(new EntityStoreListenerImpl(0, false), entity.getKey());
			}
			
		}, id.MARKERLIST);
		
		service.addEntityStoreListener(new EntityStoreListener() {
			@Override
			public void valueChanged(Entity entity) {
		//		googleMap.goToLocaltion(nodes[0].lat, nodes[0].lng);
				googleMap.drawPolyline(nodes);
				LocationCalculator calculator = new LocationCalculator(nodes);
				googleMap.clearMarker();
				MarkerEntity marker = (MarkerEntity)service.getEntity(id.GOOGLEMAPMARKER);
				calculator.getLatLng(marker.getValue()*1000);
				googleMap.addMarker(35.478495, 139.44294, marker.getIconFile());
				
				ListEntity list = (ListEntity)service.getEntity(id.MARKERLIST);
				int i = 1;
				for (Key key : list.getKeys()) {
					setIcon(service, key, calculator, i++);
				}
				
			}

			private void setIcon(DomainService service, Key key,
					LocationCalculator calculator, int i) {
				MarkerEntity marker = (MarkerEntity)service.getEntity(key);
				LatLng lng = calculator.getLatLng( marker.getValue() *1000);
				googleMap.addMarker(lng, marker.getIconFile());
			}
		}, id.TRACE);

		googleMap.setStateListener(new GoogleMapListener() {

			@Override
			public void mapReady() {
				service.addEntityStoreListener(new EntityStoreListenerImpl(0, true) , id.GOOGLEMAPMARKER);
				googleMap.addMarker(35.478495, 139.44294, ((MarkerEntity)service.getEntity(id.GOOGLEMAPMARKER)).getIconFile());
				
				ListEntity markerList = (ListEntity)service.getEntity(id.MARKERLIST);
				for (int i = 0; i < markerList.getKeys().size(); i++) {
					service.addEntityStoreListener(new EntityStoreListenerImpl(i+1, false), markerList.getKeys().get(i));
					googleMap.addMarker(35.478495,139.44294, ((MarkerEntity)service.getEntity(markerList.getKeys().get(i))).getIconFile());
				}
			}

			@Override
			public void markerMoved(int index, String address) {
				ListEntity markerList = (ListEntity)service.getEntity(id.MARKERLIST);
				MarkerEntity e = (MarkerEntity)service.getEntity(markerList.getKeys().get(index-1));
				e.setText(address);
				service.putEntity(e);
			}
			
		});

	}
	
	private void moveMarker(final GoogleMap googleMap,
			final LatLng[] nodes, Double value, int index, boolean focus) {
		LocationCalculator calc = new LocationCalculator(nodes);
		LatLng ret = calc.getLatLng(value);
		if (focus) {
			googleMap.goToLocaltion(ret.lat, ret.lng);
		}
		googleMap.moveMarker(ret.lat, ret.lng, index);
		
//		System.out.println(googleMap.getAddress(index));
	}
}
